// Copyright (C) 2007 Gameloft. All rights reserved.
// GAMELOFT PROPRIETARY/CONFIDENTIAL.
//
// Author: Laevo

#include "Graphics.h"
#include "_Math.h"
#include "Game.h"
#include "Memory.h"
#include "Debug.h"

//int cGfx::autoZ = -7878;
bool cGfx::mUseHVCenter = false;

Graphics::Graphics()
: _pTexMgr(NULL)
, mUseClip(false)
, mUseVertexColors(false)
{
	//mTargetRenderInfo.mbUniform = false;
	//SetClip( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
	_clipR.x = 0;
	_clipR.y = 0;
	_clipR.w = SCREEN_WIDTH;
	_clipR.h = SCREEN_HEIGHT;
	SetColor( 0xffffffff );
#ifdef USE_BUFFER_TEXTURE
	_pixBuffer = GL_NEW u8 [128*128*2];
#endif
	ResetTexColor();
	_translateX = _translateY = _translateZ = 0;
}

Graphics::~Graphics()
{
#ifdef USE_BUFFER_TEXTURE
	SAFE_DELETE( _pixBuffer );
#endif
}
void Graphics::DrawImage(int iTex, int dx, int dy, float scaleX)
{
	if( iTex < 0 )
		return;
	const TexInfo* tex = _pTexMgr->GetTex(iTex);
	if( tex == NULL || tex->name == -1)
		return;
#ifdef IPL_HAVE_MESSED_UP_QUADS
	DrawRegion( tex, dx, dy, 0, 0, tex->width, tex->height );
#else
	//bl: sdk20
	GLfloat rect_w = IPLMath_IntToFixed(tex->width);
    GLfloat rect_h = IPLMath_IntToFixed(tex->height);
	GLint crop_rect[] = { 0, 0, tex->width, tex->height };
	//GLfloat screen_rect[] = { IPLMath_IntToFixed(dx), IPLMath_IntToFixed(SCREEN_HEIGHT-dy), rect_w, rect_h };
	GLfloat screen_rect[] = { IPLMath_IntToFixed(dx), IPLMath_IntToFixed(SCREEN_HEIGHT-dy), dx+rect_w, SCREEN_HEIGHT-dy-rect_h };
	setStateVector( tex->ShaderInfoId );
	
	// RUIZD: Changed GL_TEXTURE_RECTANGLE_ARB for GL_TEXTURE_2D
	glBindTexture( GL_TEXTURE_2D, tex->name ); 

	// RUIZD: Replace the image draw functions with local calls
	// RUIZD: Changed GL_TEXTURE_RECTANGLE_ARB for GL_TEXTURE_2D
    // glTexParameteriv( GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop_rect );
	// IPLGLUtil_SetUniformColor4x( _texColorR, _texColorG, _texColorB, _texColorA );
	glColor4f (_texColorR, _texColorG, _texColorB, _texColorA);

    // glDrawTexxvOES(screen_rect);
	// RUIZD: Up to here
	GLfloat vertices[] =
		{
			screen_rect[0], screen_rect[1], 0, //1.0f,
			screen_rect[0], screen_rect[3], 0, //1.0f,
			screen_rect[2], screen_rect[1], 0, //1.0f,
			screen_rect[2], screen_rect[3], 0, //1.0f
		};

	GLfloat texCoord[] = {
		0.f, 0.f, 
		0.f, 1.f,
		1.f, 0.f, 
		1.f, 1.f,
	};

	tIPLGeometry _geom;
#ifdef ENABLE_QUADS
	_geom.mGeometryMode     = GL_QUADS;
#else
	_geom.mGeometryMode     = GL_TRIANGLE_STRIP;
#endif
	_geom.mCount            = 4;
	_geom.mpVertexPositions = vertices;
	_geom.mpVertexColors    = NULL;
	_geom.mpTextureCoords   = texCoord;

	//!AC_ Check if this matrix transform needs to be applied to all DrawImage
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glScalef(scaleX, 1.0f, 1.0f);
	IPLGeometry_DrawDirect(&_geom);


	ResetTexColor();
#endif
}

void Graphics::DrawRegion(int iTex, int dx, int dy, int sx, int sy, int sw, int sh, int flags)
{
	if( iTex < 0 )
		return;
	const TexInfo* tex = _pTexMgr->GetTex(iTex);
	DrawRegion(tex, dx, dy, sx, sy, sw, sh, flags);
}

void Graphics::DrawRegion(const TexInfo *tex, int dx, int dy, int sx, int sy, int sw, int sh, int flags)
{
	if( tex == NULL )
		return;
	ASSERT(tex != NULL);

	if( tex->name == -1 )
		return;
	if( (flags&HV_CENTER) == HV_CENTER)
		mUseHVCenter = true;

    //autoZ++;
	//dx++;dy++;
	//sx++; sy++;
// #ifdef __M1A__
// 	dx++;dy++;
// 	sw++;sh++;
// #endif
	GLfloat target_dx = IPLMath_IntToFixed( dx );
	GLfloat target_dy = IPLMath_IntToFixed( SCREEN_HEIGHT - dy );
	GLfloat target_mw = IPLMath_IntToFixed( sw );
	GLfloat target_mh = IPLMath_IntToFixed( sh );

	if( flags & FLAG_ROT_90 )
	{
		GLfloat temp = target_mw;
		target_mw = target_mh;
		target_mh = temp;
	}
	setStateVector( tex->ShaderInfoId );

	// RUIZD: Changed GL_TEXTURE_RECTANGLE_ARB for GL_TEXTURE_2D
	glBindTexture( GL_TEXTURE_2D, tex->name );

	// RUIZD: Call directly the OpenGL function
	// IPLGLMatrixStack_LoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// RUIZD: Replace this function call
	// IPLGLUtil_SetUniformColor4x( _texColorR, _texColorG, _texColorB, _texColorA );
	glColor4f (_texColorR, _texColorG, _texColorB, _texColorA);

	IPLGLMatrixStack_Translatex( target_dx, target_dy, 0 );


	if( g2DCommRI.transform & IS_ROT )
	{
		IPLGLMatrixStack_Rotatex( g2DCommRI.rot,
			(g2DCommRI.transform&IS_X)?1.f:0,
			(g2DCommRI.transform&IS_Y)?1.f:0,
			(g2DCommRI.transform&IS_Z)?1.f:0 );
	}

	if( g2DCommRI.transform & IS_SCALE )
    {
		IPLGLMatrixStack_Translatex( IPLMath_FixedMul(IPLMath_IntToFixed(g2DCommRI.oX_if), g2DCommRI.scaleX), IPLMath_FixedMul(IPLMath_IntToFixed(g2DCommRI.oY_if), g2DCommRI.scaleY), 0 );
		IPLGLMatrixStack_Scalex( g2DCommRI.scaleX, g2DCommRI.scaleY, 1.0f );
    }

	//glUniformMatrix4xvAPPLE( 0, 1, GL_FALSE, IPLGLMatrixStack_GetMVPx() );

	//build vertices
	GLfloat tL, tB, tR,tT, vL,vB, vR, vT;
	if( IsHVCenter() || (g2DCommRI.anchorType == Is_Center_LT2HV))
	{
		vL = -target_mw/2;
		vB = -target_mh/2;
		vR = -vL;
		vT = -vB;
        mUseHVCenter = false;
	}
	else
	{
		vL = 0;
		vB = -target_mh;
		vR = target_mw;
		vT = 0;
	}

	GLfloat vertices[] =
	{
#ifdef ENABLE_QUADS
		vL, vB, 0,  // Left-Bottom
		vL, vT, 0,  // Left-Top
		vR, vT, 0,  // Right-Top
		vR, vB, 0,  // Right-Bottom
#else
		vL, vT, 0,  // Left-Top
		vL, vB, 0,  // Left-Bottom
		vR, vT, 0,  // Right-Top
		vR, vB, 0,  // Right-Bottom
#endif

	};

//	glEnableVertexAttribArray(0);
//	glVertexAttribPointer(0, 4, GL_FIXED, GL_FALSE, 0, vertices);

	// RUIZD: Hardcodeo coordenadas de texturas
	//tL = 0.0f; //IPLMath_IntToFixed( sx );
	//tT = 0.0f; //IPLMath_IntToFixed( sy );
	//tR = 1.0f; //IPLMath_IntToFixed( sx + sw );
	//tB = 1.0f; //IPLMath_IntToFixed( sy + sh );
	tL = (float)IPLMath_IntToFixed( sx ) / (float)tex->width;
	tT = (float)IPLMath_IntToFixed( sy ) / (float)tex->height;
	tR = (float)IPLMath_IntToFixed( sx + sw ) / (float)tex->width;
	tB = (float)IPLMath_IntToFixed( sy + sh ) / (float)tex->height;

	GLfloat texCoord[] =
	{
#ifdef ENABLE_QUADS
		tL, tB,
		tL, tT,
		tR, tT,
		tR, tB
#else
		tL, tT,
		tL, tB,
		tR, tT,
		tR, tB
#endif
	};

	if( flags & FLAG_FLIP_X )
	{
		texCoord[0] = texCoord[2] = tR;
		texCoord[4] = texCoord[6] = tL;
	}
	if( flags & FLAG_FLIP_Y )
	{
		texCoord[1] = texCoord[5] = tB;
		texCoord[3] = texCoord[7] = tT;
	}
	if( flags & FLAG_ROT_90 )
	{
		GLfloat _tempX, _tempY;
		_tempX = texCoord[6]; _tempY = texCoord[7];
		texCoord[6] = texCoord[4]; texCoord[7] = texCoord[5];
		texCoord[4] = texCoord[2]; texCoord[5] = texCoord[3];
		texCoord[2] = texCoord[0]; texCoord[3] = texCoord[1];
		texCoord[0] = _tempX; texCoord[1] = _tempY;
	}

	//glEnableVertexAttribArray( 1 );
	//glVertexAttribPointer( 1, 2, GL_FIXED, GL_FALSE, 0, texCoord );

	// Vertex Colors
	/*if( mUseVertexColors )
	{
		GLfloat vtxColor[] =
		{
			0,             1.0f, 0,             1.0f
			,1.0f, 0,             0,             0
			,0,             0,             1.0f, 0
			,1.0f, 0,             1.0f, 1.0f
		};

		glEnableVertexAttribArray(2);
		glVertexAttribPointer(2, 4, GL_FIXED, GL_FALSE, 0, vtxColor);
	}*/

	//glDrawArrays( GL_QUADS, 0, 4 );

	//tIPLGeometry  geom;
#ifdef ENABLE_QUADS
	_geom.mGeometryMode     = GL_QUADS;
#else
	_geom.mGeometryMode     = GL_TRIANGLE_STRIP;
#endif
	_geom.mCount            = 4;
	_geom.mpVertexPositions = vertices;
	_geom.mpVertexColors    = NULL;
	_geom.mpTextureCoords   = texCoord;

//	IPLGLUtil_SetUniformColor4xv(color);

	IPLGeometry_DrawDirect(&_geom);

	//GLint crop_rect[] = { 0, 0, p_texture->mTextureWidth, p_texture->mTextureHeight };
	//glTexParameteriv( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_CROP_RECT_OES, crop_rect );


	ResetTexColor();
}
#ifdef _OptimizePaintFrame
void Graphics::Flush2D()
{
	setStateVector( g2DCommRI.tex->ShaderInfoId );

	// RUIZD: Changed GL_TEXTURE_RECTANGLE_ARB for GL_TEXTURE_2D
	glBindTexture( GL_TEXTURE_2D, g2DCommRI.tex->name );

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	// RUIZD: Replace this function call
	// IPLGLUtil_SetUniformColor4x( _texColorR, _texColorG, _texColorB, _texColorA );
	glColor4f (_texColorR, _texColorG, _texColorB, _texColorA);

	if( g2DCommRI.anchorType == Is_MultiFrameCenter && (g2DCommRI.transform & IS_SCALE))
	{
		GLfloat _tempX = IPLMath_IntToFixed(g2DCommRI.oX_is) +
			             IPLMath_FixedMul(IPLMath_IntToFixed(g2DCommRI.destX - g2DCommRI.oX_is), g2DCommRI.scaleX);
		GLfloat _tempY = IPLMath_IntToFixed(SCREEN_HEIGHT - g2DCommRI.oY_is) +
			             IPLMath_FixedMul(IPLMath_IntToFixed(g2DCommRI.destY - SCREEN_HEIGHT + g2DCommRI.oY_is), g2DCommRI.scaleY);
		IPLGLMatrixStack_Translatex( _tempX, _tempY, 0 );
	}
	else
	{
		// RUIZD: Call directly to OpenGL function
		glTranslatef((GLfloat) g2DCommRI.destX, (GLfloat) g2DCommRI.destY, 0);
		//IPLGLMatrixStack_Translatex( IPLMath_IntToFixed(g2DCommRI.destX), IPLMath_IntToFixed(g2DCommRI.destY), 0 );
	}

	glTranslatef(_translateX, _translateY, _translateZ);
	
	if( g2DCommRI.transform & IS_ROT )
	{
		//IPLGLMatrixStack_Rotatex( g2DCommRI.rot,
		//	(g2DCommRI.transform&IS_X)?1.0f:0,
		//	(g2DCommRI.transform&IS_Y)?1.0f:0,
		//	(g2DCommRI.transform&IS_Z)?1.0f:0 );
		IPLGLMatrixStack_Rotatex( g2DCommRI.rot,
			(g2DCommRI.transform&IS_X)?1.0f:0,
			(g2DCommRI.transform&IS_Y)?1.0f:0,
			(g2DCommRI.transform&IS_Z)?1.0f:0 );
	}

	if( g2DCommRI.transform & IS_SCALE )
	{
		IPLGLMatrixStack_Scalex( g2DCommRI.scaleX, g2DCommRI.scaleY, 1.f );
	}

	//glUniformMatrix4xvAPPLE( 0, 1, GL_FALSE, IPLGLMatrixStack_GetMVPx() );
	//glEnableVertexAttribArray( 0 );
	//glVertexAttribPointer( 0, 4, GL_FIXED, GL_FALSE, 0, gRenderQI.v );
	//glEnableVertexAttribArray( 1 );
	//glVertexAttribPointer( 1, 2, GL_FIXED, GL_FALSE, 0, gRenderQI.t );

	/*GLfloat vtxColor[] =
		{
			0,             1.0f, 0,             1.0f
			,0, 1.0f,             0,             1.0f
			,0,             1.0f,            0 , 1.0f
			,0, 1.0f,             0, 1.0f
		};

		glEnableVertexAttribArray(2);
		glVertexAttribPointer(2, 4, GL_FIXED, GL_FALSE, 0, vtxColor);	*/

	//glDrawArrays( GL_QUADS, 0, 4*gRenderQI.count );

	//tIPLGeometry  geom;
#ifdef ENABLE_QUADS
	_geom.mGeometryMode     = GL_QUADS;
	_geom.mCount            = 8*gRenderQI.count;
#else
	_geom.mGeometryMode     = GL_TRIANGLES;
	_geom.mCount            = 6*gRenderQI.count;
#endif
	_geom.mpVertexPositions = gRenderQI.v;
	_geom.mpVertexColors    = NULL;
	_geom.mpTextureCoords   = gRenderQI.t;
	//	IPLGLUtil_SetUniformColor4xv(color);
	//glColor4f (1.f, 1.f, 1.f, 1.f); //!AC_ This reset the color for modules, but must dissapear for texts
	IPLGeometry_DrawDirect(&_geom);

	//gRenderQI.count = 0;
	_bUseTexColor = false;
	g2DCommRI.transform &= (~IS_UNIFORMCOLOR);
	ResetTexColor();

	glLoadIdentity();
}
#endif

void Graphics::Flush3D()
{
	setStateVector( g3DCommRI.tex->ShaderInfoId );

	// RUIZD: Changed GL_TEXTURE_RECTANGLE_ARB for GL_TEXTURE_2D
	glBindTexture( GL_TEXTURE_2D, g3DCommRI.tex->name );

	GLfloat _cameraX = IPLMath_FloatToFixed( (T_F32)(g3DCommRI.destX - SCREEN_WIDTH_D2)/SCREEN_HEIGHT );
	GLfloat _cameraY = IPLMath_FloatToFixed( (T_F32)(SCREEN_HEIGHT_D2 - g3DCommRI.destY)/SCREEN_HEIGHT );
	GLfloat _cameraZ = IPLMath_FloatToFixed( (T_F32)g3DCommRI.destZ/120 - 1.2f );

	IPLGLMatrixStack_LoadIdentity();

	IPLGLMatrixStack_Translatex( _cameraX, _cameraY, _cameraZ );

	if( g3DCommRI.transform & IS_ROT )
	{
		IPLGLMatrixStack_Rotatex( g3DCommRI.rot,
			(g3DCommRI.transform&IS_X)?1.f:0,
			(g3DCommRI.transform&IS_Y)?1.f:0,
			(g3DCommRI.transform&IS_Z)?1.f:0 );
	}
	if( g3DCommRI.transform & IS_SCALE )
	{
		IPLGLMatrixStack_Scalex( g3DCommRI.scaleX, g3DCommRI.scaleY, 1.0f );
	}

	//glUniformMatrix4xvAPPLE( 0, 1, GL_FALSE, IPLGLMatrixStack_GetMVPx() );
	//glEnableVertexAttribArray( 0 );
	//glVertexAttribPointer( 0, 4, GL_FIXED, GL_FALSE, 0, gRenderQI.v );
	//glEnableVertexAttribArray( 1 );
	//glVertexAttribPointer( 1, 2, GL_FIXED, GL_FALSE, 0, gRenderQI.t );
	//glDrawArrays( GL_QUADS, 0, 4*gRenderQI.count );

	//tIPLGeometry  geom;
#ifdef ENABLE_QUADS
	_geom.mGeometryMode     = GL_QUADS;
#else
	_geom.mGeometryMode     = GL_TRIANGLE_STRIP;
#endif
	_geom.mCount            = 4*gRenderQI.count;
	_geom.mpVertexPositions = gRenderQI.v;
	_geom.mpVertexColors    = NULL;
	_geom.mpTextureCoords   = gRenderQI.t;
	//	IPLGLUtil_SetUniformColor4xv(color);
	IPLGeometry_DrawDirect(&_geom);

	gRenderQI.count = 0;
}

#ifdef _TestEnable
void Graphics::DrawRegionIn2D(const Texture *tex, int dx, int dy, int sx, int sy, int sw, int sh, int flags)
{
}
void Graphics::DrawCircleTest(int x, int y, int radius)
{
	IPLGLStateVector_SetCurrentToBuiltin( IPL_BSV_UNIFORMBLENDING );
	IPLGLMatrixStack_LoadIdentity();
	//glUniformMatrix4xvAPPLE(0, 1, GL_FALSE, IPLGLMatrixStack_GetMVPx());
	IPLGLUtil_SetUniformColor4x(4, _nativeColorR, _nativeColorG, _nativeColorB, _nativeColorA);

	//radius = 1;
	GLfloat* vert = GL_NEW GLfloat [16*radius];
	GLint v_index = 0;
	int _r = radius * radius;
	GLfloat _off = IPLMath_FloatToFixed(0.4f);

	for (int i = 0; i < radius; i++)
	{
		GLfloat xoff = IPLMath_IntToFixed(i) ;
		GLfloat yoff = IPLMath_FixedSqrt( IPLMath_IntToFixed(_r - i * i) );

		/*GLfloat left = IPLMath_IntToFixed(x+xoff) - _off;
		GLfloat right = IPLMath_IntToFixed(x+xoff) + _off;
		GLfloat bottom = IPLMath_IntToFixed(y+yoff) - _off;
		GLfloat top = IPLMath_IntToFixed(y+yoff) + _off;*/
		GLfloat left = IPLMath_IntToFixed(x)+xoff-_off;
		GLfloat right = IPLMath_IntToFixed(x)+xoff+_off;
		GLfloat bottom = IPLMath_IntToFixed(y)-yoff-_off;
		GLfloat top = IPLMath_IntToFixed(y)-yoff+_off;

		vert[v_index++] = left;
		vert[v_index++] = bottom;
		vert[v_index++] = 0;
		vert[v_index++] = 1.0f;

		vert[v_index++] = left;
		vert[v_index++] = top;
		vert[v_index++] = 0;
		vert[v_index++] = 1.0f;

		vert[v_index++] = right;
		vert[v_index++] = top;
		vert[v_index++] = 0;
		vert[v_index++] = 1.0f;

		vert[v_index++] = right;
		vert[v_index++] = bottom;
		vert[v_index++] = 0;
		vert[v_index++] = 1.0f;
	}
	glVertexAttribPointer(0, 4, GL_FIXED, GL_FALSE, 0, vert);
	glEnableVertexAttribArray(0);
	glDrawArrays(GL_QUADS, 0, 4*radius);
	SAFE_DELETE( vert );
}
#endif

//void Graphics::DrawWave(int iTex, int dx, int dy, int counter)
//{
//	if( iTex < 0 )
//	{
//		//ASSERT(0);
//		return;
//	}
//	dy = SCREEN_HEIGHT - dy;
//	//dy += CMath::Rand(-3,3);
//	const TexInfo* tex = _pTexMgr->GetTex(iTex);
//	int w = tex->width;
//	int h = tex->height;
//
//	IPLGLStateVector_SetCurrentToBuiltin( tex->stateVector );
//    glActiveTexture(GL_TEXTURE0);
//	glBindTexture( GL_TEXTURE_RECTANGLE_ARB, tex->name );
//	IPLGLMatrixStack_LoadIdentity();
//
//	IPLGLMatrixStack_Translatex( IPLMath_IntToFixed(dx), IPLMath_IntToFixed(dy), 0 );
//
//	glUniformMatrix4xvAPPLE( 0, 1, GL_FALSE, IPLGLMatrixStack_GetMVPx() );
//
//#define stepLen  2
//	GLfloat vertices[320*16/stepLen];
//	int offset = 0;
//	//build vertices
//	int _phase = counter%30;
//	int _amplitude = (counter%3+1)*4;//CMath::Rand(16,32);
//	for( int i = 0; i < 320/stepLen; i++ )
//	{
//		T_F32 _yy1 = (T_F32)sinf(i*3.14f/78.f + _phase)*_amplitude;
//		T_F32 _yy2 = (T_F32)sinf((i+1)*3.14f/78.f + _phase)*_amplitude;
//		vertices[offset++] = IPLMath_IntToFixed( i*stepLen ); vertices[offset++] = IPLMath_FloatToFixed( _yy1-h ); vertices[offset++] = autoZ; vertices[offset++] = 1.0f;
//		vertices[offset++] = IPLMath_IntToFixed( i*stepLen ); vertices[offset++] = IPLMath_FloatToFixed( _yy1 ); vertices[offset++] = autoZ; vertices[offset++] = 1.0f;
//		vertices[offset++] = IPLMath_IntToFixed( i*stepLen+stepLen ); vertices[offset++] = IPLMath_FloatToFixed( _yy2 ); vertices[offset++] = autoZ; vertices[offset++] = 1.0f;
//		vertices[offset++] = IPLMath_IntToFixed( i*stepLen+stepLen ); vertices[offset++] = IPLMath_FloatToFixed( _yy2-h ); vertices[offset++] = autoZ; vertices[offset++] = 1.0f;
//	}
//
//	GLfloat texCoord[320*8/stepLen];
//	offset = 0;
//
//	for( int i = 0; i < 320/stepLen; i++ )
//	{
//		texCoord[offset++] = IPLMath_IntToFixed( 0 ); texCoord[offset++] = IPLMath_IntToFixed( h );
//		texCoord[offset++] = IPLMath_IntToFixed( 0 ); texCoord[offset++] = IPLMath_IntToFixed( 0 );
//		texCoord[offset++] = IPLMath_IntToFixed( w ); texCoord[offset++] = IPLMath_IntToFixed( 0 );
//		texCoord[offset++] = IPLMath_IntToFixed( w ); texCoord[offset++] = IPLMath_IntToFixed( h );
//	}
//
//	glVertexAttribPointer( 0, 4, GL_FIXED, GL_FALSE, 0, vertices );
//	glEnableVertexAttribArray( 0 );
//	glVertexAttribPointer( 1, 2, GL_FIXED, GL_FALSE, 0, texCoord );
//	glEnableVertexAttribArray( 1 );
//
//	glDrawArrays( GL_QUADS, 0, 320*4/stepLen );
//#undef stepLen
//
//}

void Graphics::DrawLine(int xB, int yB, int xE, int yE, int lineWidth)
{
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	yB = SCREEN_HEIGHT - yB;
	yE = SCREEN_HEIGHT - yE;
	/*
	int left, top, width, height;
	left = CMath::Min(xB,xE);
	top  = CMath::Max(yB,yE);
	width = xB - left + xE - left;
	height = top - yB  + top - yE;
	_clipRect2Gfx(&left,&top,&width,&height);

	if( width <=0 || height<=0)
		return;
	if(xB < xE)
	{
		xB = left;
		xE = left + width;
	}
	else
	{
		xE = left;
		xB = left + width;
	}

	if(yB > yE)
	{
		yB = top;
		yE = top - height;
	}
	else
	{
		yE = top;
		yB = top - height;
	}*/
	IPLGLStateVector_SetCurrentToBuiltin( IPL_BSV_UNIFORMBLENDING );
	IPLGLMatrixStack_LoadIdentity();
	//glUniformMatrix4xvAPPLE(0, 1, GL_FALSE, IPLGLMatrixStack_GetMVPx());

	T_F32 x0, y0, x1, y1, x2, y2, x3, y3;
	if( CMath::Abs(yE - yB) < CMath::Abs(xE - xB) )
	{
		x0 = (T_F32)xB - lineWidth * .5f;
		y0 = (T_F32)yB - lineWidth * .5f;
		x1 = (T_F32)xE + lineWidth * .5f;
		y1 = (T_F32)yE - lineWidth * .5f;
		x2 = (T_F32)xE + lineWidth * .5f;
		y2 = (T_F32)yE + lineWidth * .5f;
		x3 = (T_F32)xB - lineWidth * .5f;//x3=x0
		y3 = (T_F32)yB + lineWidth * .5f;
	}
	else {
		x0 = (T_F32)xB - lineWidth * .5f;//
		y0 = (T_F32)yB - lineWidth * .5f;
		x1 = (T_F32)xB + lineWidth * .5f;
		y1 = (T_F32)yB - lineWidth * .5f;
		x2 = (T_F32)xE + lineWidth * .5f;//x2 ==
		y2 = (T_F32)yE + lineWidth * .5f;
		x3 = (T_F32)xE - lineWidth * .5f;
		y3 = (T_F32)yE + lineWidth * .5f;
	}
	//GLuint mBufferNames;
	//glGenBuffers(1,&mBufferNames);
	GLfloat vertices[] =
	{
		IPLMath_FloatToFixed( x0 ), IPLMath_FloatToFixed( y0 ), 0, //1.0f,
		IPLMath_FloatToFixed( x1 ), IPLMath_FloatToFixed( y1 ), 0, //1.0f,

		IPLMath_FloatToFixed( x3 ), IPLMath_FloatToFixed( y3 ), 0, //1.0f,		
		IPLMath_FloatToFixed( x2 ), IPLMath_FloatToFixed( y2 ), 0, //1.0f,

	};

	//glBindBuffer(GL_ARRAY_BUFFER, mBufferNames);
	//glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * 4, (const GLvoid*)vertices, GL_STATIC_DRAW);

	//glEnableVertexAttribArray(0);
	//glVertexAttribPointer(0, 4, GL_FIXED, GL_FALSE, 0, vertices);
	//glVertexAttribPointer(0, 4, GL_FIXED, GL_FALSE, 0, 0);

	// RUIZD: Replace this function call
	// IPLGLUtil_SetUniformColor4x( _nativeColorR, _nativeColorG, _nativeColorB, _nativeColorA );
	glColor4f( _nativeColorR, _nativeColorG, _nativeColorB, _nativeColorA );
	//glDrawArrays(GL_QUADS, 0, 4);
	
#ifdef ENABLE_QUADS
	_geom.mGeometryMode     = GL_QUADS;
	_geom.mCount            = 4;
#else
	_geom.mGeometryMode     = GL_TRIANGLE_STRIP;
	_geom.mCount            = 4;
#endif
	_geom.mpVertexPositions = vertices;
	_geom.mpVertexColors    = NULL;
	_geom.mpTextureCoords   = NULL;

	IPLGeometry_DrawDirect(&_geom);

	//glDeleteBuffers( 1, &mBufferNames );
	//glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Graphics::DrawRect(int x, int y, int w, int h, int border)
{
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	IPLGLStateVector_SetCurrentToBuiltin( IPL_BSV_UNIFORMBLENDING );
	IPLGLMatrixStack_LoadIdentity();
	
	// RUIZD: Replace this function call
	// IPLGLUtil_SetUniformColor4x( _nativeColorR , _nativeColorG, _nativeColorB, _nativeColorA );
	glColor4f (_nativeColorR, _nativeColorG, _nativeColorB, _nativeColorA);

	//build vertices
	GLfloat left   = IPLMath_IntToFixed(x);
	GLfloat right  = IPLMath_IntToFixed(x + w);
	GLfloat bottom = IPLMath_IntToFixed(SCREEN_HEIGHT - y - h);
	GLfloat top    = IPLMath_IntToFixed(SCREEN_HEIGHT - y);
	GLfloat _border = IPLMath_IntToFixed(border);

	GLfloat vertices[] =
	{
		left,  top,					0, //1.0f,
		right, top,					0, //1.0f,
		right, top - _border,		0, //1.0f,

		left,  top,					0, //1.0f,
		left,  top - _border,		0, //1.0f,
		right, top - _border,		0, //1.0f,

		right - _border, top - _border,		0, //1.0f,
		right,			 top - _border,		0, //1.0f,
		right,			 bottom + _border,  0, //1.0f,

		right - _border,	top - _border,		0, //1.0f,
		right,			bottom + _border,    0, //1.0f,
		right - _border, bottom + _border,    0, //1.0f,

		left,  bottom + _border,	0, //1.0f,
		right, bottom + _border,	0, //1.0f,
		right, bottom,				0, //1.0f,

		right, bottom,				0, //1.0f,
		left,  bottom,				0, //1.0f,
		left,  bottom + _border,	0, //1.0f,

		left,			top - _border,		0, //1.0f,
		left + _border,	top - _border,		0, //1.0f,
		left + _border,	bottom,     0, //1.0f,

		left,			top - _border,		0, //1.0f,
		left,			bottom + _border,	0, //1.0f,
		left + _border,	bottom + _border,   0, //1.0f,

	};

	//glVertexAttribPointer(0, 4, GL_FIXED, GL_FALSE, 0, vertices);
	//glEnableVertexAttribArray(0);

	//draw the rectangle
	//glDrawArrays(GL_QUADS, 0, 16);

	//tIPLGeometry  geom;
#ifdef ENABLE_QUADS
	_geom.mGeometryMode     = GL_QUADS;
#else
	_geom.mGeometryMode     = GL_TRIANGLES;
#endif
	_geom.mCount            = 24;
	_geom.mpVertexPositions = vertices;
	_geom.mpVertexColors    = NULL;
	_geom.mpTextureCoords   = NULL;
	//	IPLGLUtil_SetUniformColor4xv(color);
	IPLGeometry_DrawDirect(&_geom);
}

void Graphics::DrawBorderedRect(int x, int y, int w, int h)
{
	// RUIZD: Draw a border rect in other way
	// IPLGLStateVector_SetCurrentToBuiltin( IPL_BSV_COLORBLENDING ); //IPL_BSV_UNIFORMBLENDING

	IPLGLMatrixStack_LoadIdentity();
	

	tIPLRect rect;
	rect.mX = IPLMath_IntToFixed(x);
	rect.mY = IPLMath_IntToFixed(SCREEN_HEIGHT-y);
	rect.mW = IPLMath_IntToFixed(w);
	rect.mH = IPLMath_IntToFixed(h);	

	//tIPLGeometry geom;

	// RUIZD: Draw a border rect in other way
	// IPLGeometry_GenBorderedRect(&geom, &rect, 1.5f, IPLMath_FloatToFixed(1.1f));
	// IPLGeometry_DrawObject(&geom);
}

/**
 * Paints or updates the fade in/out transition
 *
 * @param kindOf		The type of fade to do
 * @param paint			A boolean variable to let the method know if we need to paint or just the update
 * @returns				True, if the transition is over
 */
int _savedSelectionIdx;
bool Graphics::PaintAndUpdateTransition(int kindOf, bool paint)
{
	static int fadeState = 0;
	static int fadeCnt = 0;
	static int fadeReturn = 0;

	if (paint)
	{
		int alphaVal = (fadeCnt > 0xFF) ? 0xFF:(fadeCnt < 0) ? 0:fadeCnt;
		if(alphaVal > 0)
		{
			getGfx()->SetColor(0x000000 | (alphaVal << 24));
			getGfx()->FillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
		}
	}
	else
	{
		if (fadeState != kindOf)
		{
			fadeCnt = (kindOf == FADE_IN) ? 0xFF:0;
			fadeState = kindOf;
		}

		fadeCnt += FADE_STEPS * fadeState;

		switch (fadeState)
		{
			case FADE_IN:
			{
				if (fadeCnt > -(FADE_STEPS*2))
				{
					return false;
				}
				fadeCnt = -(FADE_STEPS*2);
				break;
			}

			case FADE_OUT:
			{
				if (fadeCnt < 0xFF + (FADE_STEPS*2))
				{
					return false;
				}
				fadeCnt = 0xFF + (FADE_STEPS*2);
				break;
			}
		}
	}

	return true;
}


void Graphics::FillRect(int x, int y, int w, int h)
{
	y = SCREEN_HEIGHT - y - h;

	_clipRect2Gfx( &x, &y, &w, &h );
	if( (w <= 0) || (h <= 0) )
		return;
	IPLGLStateVector_SetCurrentToBuiltin( IPL_BSV_UNIFORMBLENDING );
	IPLGLMatrixStack_MatrixMode(IPL_MSE_MODELVIEW);
	IPLGLMatrixStack_LoadIdentity();
	//glUniformMatrix4xvAPPLE(0, 1, GL_FALSE, IPLGLMatrixStack_GetMVPx());

	T_F32 x0, y0, x1, y1, x2, y2, x3, y3;

	x0 = (T_F32)x;
	y0 = (T_F32)y;
	x1 = (T_F32)x;
	y1 = (T_F32)(y + h);
	x2 = (T_F32)(x + w);
	y2 = (T_F32)(y + h);
	x3 = (T_F32)(x + w);
	y3 = (T_F32)y;

	//GLuint mBufferNames;
	//glGenBuffers(1,&mBufferNames);
	GLfloat vertices[] =
	{
		IPLMath_FloatToFixed( x0 ), IPLMath_FloatToFixed( y0 ), 0, //1.0f,
		IPLMath_FloatToFixed( x1 ), IPLMath_FloatToFixed( y1 ), 0, //1.0f,
		
		IPLMath_FloatToFixed( x3 ), IPLMath_FloatToFixed( y3 ), 0, //1.0f,
		IPLMath_FloatToFixed( x2 ), IPLMath_FloatToFixed( y2 ), 0, //1.0f,
	};

	//glBindBuffer(GL_ARRAY_BUFFER, mBufferNames);
	//glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * 4, (const GLvoid*)vertices, GL_STATIC_DRAW);

	//glEnableVertexAttribArray(0);
	//glVertexAttribPointer(0, 4, GL_FIXED, GL_FALSE, 0, vertices);
	////glVertexAttribPointer(0, 4, GL_FIXED, GL_FALSE, 0, 0);

	// RUIZD: Change later
	// IPLGLUtil_SetUniformColor4x( _nativeColorR, _nativeColorG, _nativeColorB, _nativeColorA );
	glColor4f (_nativeColorR, _nativeColorG, _nativeColorB, _nativeColorA);
	//glDrawArrays(GL_QUADS, 0, 4);
	//glDeleteBuffers( 1, &mBufferNames );
	//glBindBuffer(GL_ARRAY_BUFFER, 0);

	//tIPLGeometry  geom;
#ifdef ENABLE_QUADS
	_geom.mGeometryMode     = GL_QUADS;
	_geom.mCount            = 4;
#else
	_geom.mGeometryMode     = GL_TRIANGLE_STRIP;
	_geom.mCount            = 4;
#endif
	_geom.mpVertexPositions = vertices;
	_geom.mpVertexColors    = NULL;
	_geom.mpTextureCoords   = NULL;
	//	IPLGLUtil_SetUniformColor4xv(color);
	IPLGeometry_DrawDirect(&_geom);
}

void Graphics::SetClip(int x, int y, int width, int height)
{
	if( (x > SCREEN_WIDTH) || ( y > SCREEN_HEIGHT) || width < 0 || height < 0 )
		return;
	if( x < 0 )
	{
		width -= x;
		x = 0;
	}
	if( y < 0 )
	{
		height -= y;
		y = 0;
	}

	if( (x + width) > SCREEN_WIDTH )
		width = SCREEN_WIDTH - x;
	if( (y + height) > SCREEN_HEIGHT )
		height = SCREEN_HEIGHT - y;
	_clipR.x = x;
	_clipR.y = y;
	_clipR.w = width;
	_clipR.h = height;
	mUseClip = true;
}

void Graphics::_clipRect2Gfx(int *x,int *y,int *w,int *h)
{
	int dstx = CMath::Max(_clipR.x, *x);
	int dsty = CMath::Max(_clipR.y, *y);
	int dstw = CMath::Min(_clipR.x + _clipR.w , *x + *w) - dstx;
	int dsth = CMath::Min(_clipR.y + _clipR.h , *y + *h) - dsty;
	*x=dstx;
	*y=dsty;
	*w=dstw;
	*h=dsth;
}

bool Graphics::_clipRect2Tex(int *dx,int *dy, int *mx,int *my,int *mw,int *mh)
{
	if( !mUseClip )
		return true;
	if( (*dx + *mw < _clipR.x)
		|| (*dx > _clipR.x + _clipR.w)
		|| (*dy + *mh < _clipR.y)
		|| (*dy > _clipR.y + _clipR.h) )
		return false;

	int ds = _clipR.x - *dx;
	if( ds > 0 )
	{
		*mx = *mx + ds;
		*mw = *mw - ds;
		*dx = _clipR.x;
	}
	ds = _clipR.y - *dy;
	if( ds > 0 )
	{
		*my = *my + ds;
		*mh = *mh - ds;
		*dy = _clipR.y;
	}
	ds = _clipR.x + _clipR.w - (*dx + *mw);
	if( ds < 0 )
		*mw = *mw + ds;
	ds = _clipR.y + _clipR.h - (*dy + *mh);
	if( ds < 0 )
		*mh = *mh + ds;
	return true;
}

void Graphics::DrawCircle(int x, int y, int radius)
{
	IPLGLMatrixStack_LoadIdentity();
	// not so efficient way of drawing a circle ...
	const int circleSteps = IPLMath_FixedToInt(radius / 2);

	IPLGLStateVector_SetCurrentToBuiltin( IPL_BSV_UNIFORMBLENDING );
	IPLGLMatrixStack_LoadIdentity();
	
	// RUIZD: Change later
	// IPLGLUtil_SetUniformColor4x( _nativeColorR, _nativeColorG, _nativeColorB, _nativeColorA );
	glColor4f (_nativeColorR, _nativeColorG, _nativeColorB, _nativeColorA);

	GLfloat* vert = GL_NEW GLfloat [16*circleSteps];
	GLint v_index = 0;

	for (int i = 1; i < circleSteps; i++)
	{
		GLfloat xoff = (GLfloat)(IPLMath_IntToFixed(radius) * cosf(IPL_FLOAT_PI / 2 * i / circleSteps));
		GLfloat yoff = (GLfloat)(IPLMath_IntToFixed(radius) * sinf(IPL_FLOAT_PI / 2 * i / circleSteps));

		GLfloat left = IPLMath_IntToFixed(x) - xoff;
		GLfloat right = IPLMath_IntToFixed(x) + xoff;
		GLfloat bottom = IPLMath_IntToFixed(y) - yoff;
		GLfloat top = IPLMath_IntToFixed(y) + yoff;

		vert[v_index++] = left;
		vert[v_index++] = bottom;
		vert[v_index++] = 0;
		vert[v_index++] = 1.0f;

		vert[v_index++] = left;
		vert[v_index++] = top;
		vert[v_index++] = 0;
		vert[v_index++] = 1.0f;

		vert[v_index++] = right;
		vert[v_index++] = top;
		vert[v_index++] = 0;
		vert[v_index++] = 1.0f;

		vert[v_index++] = right;
		vert[v_index++] = bottom;
		vert[v_index++] = 0;
		vert[v_index++] = 1.0f;
	}
	//glVertexAttribPointer(0, 4, GL_FIXED, GL_FALSE, 0, vert);
	//glEnableVertexAttribArray(0);
	//glDrawArrays(GL_QUADS, 0, 4*circleSteps);
	//tIPLGeometry  geom;
#ifdef ENABLE_QUADS
	_geom.mGeometryMode     = GL_QUADS;
#else
	_geom.mGeometryMode     = GL_TRIANGLE_STRIP;
#endif
	_geom.mCount            = 4*circleSteps;
	_geom.mpVertexPositions = vert;
	_geom.mpVertexColors    = NULL;
	_geom.mpTextureCoords   = NULL;
	//	IPLGLUtil_SetUniformColor4xv(color);
	IPLGeometry_DrawDirect(&_geom);

	SAFE_DELETE( vert );
}

void Graphics::SetColor(int argb)
{
	_nativeColorB = ((argb << 8) & 0xff00) / 65280.f;
	_nativeColorG = ((argb      ) & 0xff00) / 65280.f;
	_nativeColorR = ((argb >> 8) & 0xff00) / 65280.f;
	_nativeColorA = ((argb >> 16) & 0xff00) / 65280.f;
}

void Graphics::SetTexColor(int argb)
{
	_texColorB = ((argb << 8) & 0xff00) / 65280.f;
	_texColorG = ((argb      ) & 0xff00) / 65280.f;
	_texColorR = ((argb >> 8) & 0xff00) / 65280.f;
	_texColorA = ((argb >> 16) & 0xff00) / 65280.f;
	g2DCommRI.transform |= IS_UNIFORMCOLOR;
}

void Graphics::ResetTexColor()
{
	_texColorB =
	_texColorG =
	_texColorR =
	_texColorA = 1.f;
}

#ifdef USE_BUFFER_TEXTURE
void* Graphics::_getOffset(int x, int y)
{
	return _pixBuffer + y * _pixPitch + (x << _pixShift);
}

void inline Graphics::_drawPoint(void *dst)
{
	int alpha = (_colorARGB >> 24) & 0xFF;
	if(alpha == 0xFF)
	{
		*((short*)dst) = _nativeColor;
	}
	else if( alpha > 0 )
	{
		int r_src = (_colorARGB >> 16) & 0xFF;
		int g_src = (_colorARGB >>  8) & 0xFF;
		int b_src = _colorARGB & 0xFF;

		int r_dest = (int)(((((*((short*)dst)) & 0xF800)>>11)<<3)&0xFF);
		int g_dest = (int)(((((*((short*)dst)) & 0x07E0)>> 5)<<2)&0xFF);
		int b_dest = (int)((( (*((short*)dst)) & 0x001F     )<<3)&0xFF);

		r_dest = ((r_src * alpha + r_dest * (256- alpha)) >> 8) & 0xFF;
		g_dest = ((g_src * alpha + g_dest * (256- alpha)) >> 8) & 0xFF;
		b_dest = ((b_src * alpha + b_dest * (256- alpha)) >> 8) & 0xFF;

		*((short*)dst) = TO_RGB(r_dest,g_dest,b_dest);
	}
}

//inline void Graphics::_drawPoint( int x, int y)
//{
//	if(x < _clipR.x || x >= _clipR.y || y < _clipR.w || y >= _clipR.h )
//		return;
//	void * d = _getOffset(x, y);
//	_drawPoint(d);
//}

void Graphics::_drawPoint(int x, int y)
{
	//if( x < _clipR.x || x >= _clipR.y || y < _clipR.w || y >= _clipR.h )
	//	return;
	IPLGLStateVector_SetCurrentToBuiltin( IPL_BSV_UNIFORMBLENDING );

	// RUIZD: Change later
	// IPLGLUtil_SetUniformColor4x( _nativeColorR , _nativeColorG, _nativeColorB, _nativeColorA );
	glColor4f (_nativeColorR, _nativeColorG, _nativeColorB, _nativeColorA);

	GLfloat vertices[] =
	{
		//IPLMath_IntToFixed(x - SCREEN_WIDTH_D2),  IPLMath_IntToFixed(SCREEN_HEIGHT_D2 - y), 0, //1.0f,
		IPLMath_IntToFixed(x),  IPLMath_IntToFixed(SCREEN_HEIGHT - y), 0, //1.0f,
	};

	//glVertexAttribPointer( 0, 4, GL_FIXED, GL_FALSE, 0, vertices );
	//glEnableVertexAttribArray( 0 );

	//draw the point
	//glDrawArrays( GL_POINTS, 0, 1 );
	//tIPLGeometry  geom;
	_geom.mGeometryMode     = GL_POINTS;
	_geom.mCount            = 1;
	_geom.mpVertexPositions = vertices;
	_geom.mpVertexColors    = NULL;
	_geom.mpTextureCoords   = NULL;
	//	IPLGLUtil_SetUniformColor4xv(color);
	IPLGeometry_DrawDirect(&_geom);
}

void Graphics::DrawSymetryPoints(int orgX, int orgY, int x, int y, bool isOdd)
{
	int a = isOdd ? 0 : 1;

	_drawPoint(orgX + x,     orgY + y-a);
	_drawPoint(orgX + x,     orgY - y  );
	_drawPoint(orgX - x-a,   orgY + y-a);
	_drawPoint(orgX - x-a,   orgY - y  );
	_drawPoint(orgX + y-a,   orgY + x  );
	_drawPoint(orgX + y-a,   orgY - x-a);
	_drawPoint(orgX - y,     orgY + x  );
	_drawPoint(orgX - y,     orgY - x-a);
}

//copy from Computer Graphics Principle and Practice. p87
void Graphics::DrawCircle2(int orgX, int orgY, int width)
{
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	int r = width;

	int x = 0;
	int y = r;
	int d = 1 - r;
	int deltaE = 3;
	int deltaSE = -2 * r + 5;
	DrawSymetryPoints(orgX , orgY ,x, y , (width & 1)!= 0);
	while( y > x ) {
		if( d < 0) {
			d += deltaE;
			deltaE += 2;
			deltaSE += 2;
		}else {
			d += deltaSE;
			deltaE += 2;
			deltaSE += 4;
			y--;
		}
		x++;
		if(y >= x)
			DrawSymetryPoints(orgX , orgY ,x, y  , (width & 1) != 0);
	}
}

void Graphics::DrawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
{
	height = height;
	startAngle = startAngle;
	arcAngle = arcAngle;

	int r = width >> 1;
	DrawCircle2(x+r,y+r,width);
}
#endif
void Graphics::DrawRegionIn3D(const ObjCommonRenderInfo & texInfo)
{
	gRenderQI.count = 0;
	GLfloat tL, tB, tR,tT, vL,vB, vR, vT, vZ;
	if( texInfo.transform & IS_TOP )
	{
		vL = IPLMath_FloatToFixed( (T_F32)(-texInfo.modW/2)/SCREEN_HEIGHT );
		vB = IPLMath_FloatToFixed( (T_F32)(-texInfo.modH)/SCREEN_HEIGHT );
		vR = IPLMath_FloatToFixed( (T_F32)(+texInfo.modW/2)/SCREEN_HEIGHT );
		vT = IPLMath_FloatToFixed( (T_F32)(0)/SCREEN_HEIGHT );
	}
	else if( texInfo.transform & IS_BOTTOM )
	{
		vL = IPLMath_FloatToFixed( (T_F32)(-texInfo.modW/2)/SCREEN_HEIGHT );
		vB = IPLMath_FloatToFixed( (T_F32)(0)/SCREEN_HEIGHT );
		vR = IPLMath_FloatToFixed( (T_F32)(+texInfo.modW/2)/SCREEN_HEIGHT );
		vT = IPLMath_FloatToFixed( (T_F32)(+texInfo.modH)/SCREEN_HEIGHT );
	}
	else
	{
		vL = IPLMath_FloatToFixed( (T_F32)(-texInfo.modW/2)/SCREEN_HEIGHT );
		vB = IPLMath_FloatToFixed( (T_F32)(-texInfo.modH/2)/SCREEN_HEIGHT );
		vR = IPLMath_FloatToFixed( (T_F32)(+texInfo.modW/2)/SCREEN_HEIGHT );
		vT = IPLMath_FloatToFixed( (T_F32)(+texInfo.modH/2)/SCREEN_HEIGHT );
	}
	/*vL = IPLMath_FloatToFixed( -0.5f );
	vB = IPLMath_FloatToFixed( -0.5f );
	vR = IPLMath_FloatToFixed( 0.5f );
	vT = IPLMath_FloatToFixed( 0.5f );*/
	vZ = IPLMath_FloatToFixed( -0.000f );
	GLfloat vertices[] =
	{
		vL, vB, vZ, //1.0f,
		vL, vT, vZ, //1.0f,
#ifdef IPL_HAVE_MESSED_UP_QUADS
		vR, vB, vZ, //1.0f,
		vR, vT, vZ, //1.0f
#else
		vR, vT, vZ, //1.0f,
		vR, vB, vZ, //1.0f
#endif
	};

	tL = IPLMath_FloatToFixed( (T_F32)texInfo.modX );
	tT = IPLMath_FloatToFixed( (T_F32)texInfo.modY );
	tR = IPLMath_FloatToFixed( (T_F32)texInfo.modX + (T_F32)texInfo.modW );
	tB = IPLMath_FloatToFixed( (T_F32)texInfo.modY + (T_F32)texInfo.modH );
	GLfloat texCoord[] =
	{
		tL, tB,
		tL, tT,
#ifdef IPL_HAVE_MESSED_UP_QUADS
		tR, tB,
		tR, tT
#else
		tR, tT,
		tR, tB
#endif
	};

	int pos = gRenderQI.count*12;
	//MEMCPY( gRenderQI.v + pos, vertices, 16*sizeof(GLfloat) );
	MEMCPY( gRenderQI.v + pos, vertices, sizeof(vertices) );
	pos = gRenderQI.count*8;
	//MEMCPY( gRenderQI.t + pos, texCoord, 8*sizeof(GLfloat) );
	MEMCPY( gRenderQI.t + pos, texCoord, sizeof(texCoord) );
	gRenderQI.count++;
	Flush3D();
}

void Graphics::DrawRay(int x, int y, int arcAngle, int length, int angle)
{
	int angle1 = CMath::ToDSAngle(angle - arcAngle/2);
	int angle2 = CMath::ToDSAngle(angle + arcAngle/2);

	int x1 = x + ((length * CMath::Cos(angle1)) >> 8); 
    int y1 = y + ((length * CMath::Sin(angle1)) >> 8); 
    int x2 = x + ((length * CMath::Cos(angle2)) >> 8); 
    int y2 = y + ((length * CMath::Sin(angle2)) >> 8); 

	FillTriangle(x, y, x1, y1, x2, y2);
}

void Graphics::FillTriangle(int x0, int y0, int x1, int y1, int x2, int y2)
{
	IPLGLStateVector_SetCurrentToBuiltin( IPL_BSV_UNIFORMBLENDING );
	IPLGLMatrixStack_LoadIdentity();
	//	IPLGLStateVector_SetCurrentToBuiltin(IPL_BSV_COLORFP);

	// RUIZD: Change later
	// IPLGLUtil_SetUniformColor4x( _nativeColorR , _nativeColorG, _nativeColorB, _nativeColorA );
	glColor4f (_nativeColorR, _nativeColorG, _nativeColorB, _nativeColorA);

	//build vertices
	GLfloat vertices[] =
	{
	/*	IPLMath_IntToFixed(x0 - SCREEN_WIDTH_D2),  IPLMath_IntToFixed(SCREEN_HEIGHT_D2 - y0), 0, 1.0f,
		IPLMath_IntToFixed(x1 - SCREEN_WIDTH_D2),  IPLMath_IntToFixed(SCREEN_HEIGHT_D2 - y1), 0, 1.0f,
		IPLMath_IntToFixed(x2 - SCREEN_WIDTH_D2),  IPLMath_IntToFixed(SCREEN_HEIGHT_D2 - y2), 0, 1.0f*/
		IPLMath_IntToFixed(x0),  IPLMath_IntToFixed(SCREEN_HEIGHT - y0), 0, //1.0f,
		IPLMath_IntToFixed(x1),  IPLMath_IntToFixed(SCREEN_HEIGHT - y1), 0, //1.0f,
		IPLMath_IntToFixed(x2),  IPLMath_IntToFixed(SCREEN_HEIGHT - y2), 0, //1.0f
	};
	/*GLuint mBufferNames;
	glGenBuffers(1,&mBufferNames);
	glBindBuffer(GL_ARRAY_BUFFER, mBufferNames);
	glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * 4, (const GLvoid*)vertices, GL_STATIC_DRAW);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 4, GL_FIXED, GL_FALSE, 0, 0);*/

	//IPLGLUtil_SetUniformColor4x( 4, _nativeColorR, _nativeColorG, _nativeColorB, _nativeColorA );

	//glDrawArrays(GL_QUADS, 0, 4);

	//glVertexAttribPointer( 0, 4, GL_FIXED, GL_FALSE, 0, vertices );
	//glEnableVertexAttribArray( 0 );

	//draw the triangles
	//glDrawArrays( GL_TRIANGLE_STRIP/*GL_TRIANGLES*/, 0, 3 );

	//tIPLGeometry  geom;
	_geom.mGeometryMode     = GL_TRIANGLE_STRIP;
	_geom.mCount            = 3;
	_geom.mpVertexPositions = vertices;
	_geom.mpVertexColors    = NULL;
	_geom.mpTextureCoords   = NULL;
	//	IPLGLUtil_SetUniformColor4xv(color);
	IPLGeometry_DrawDirect(&_geom);

	//glDeleteBuffers( 1, &mBufferNames );
	//glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Graphics::DrawPoint(int x, int y)
{
	IPLGLStateVector_SetCurrentToBuiltin( IPL_BSV_UNIFORMBLENDING );
	//IPLGLMatrixStack_LoadIdentity();
	//IPLGLMatrixStack_Scalef( 5.0f, 5.0f, 1.0f );
	//glUniformMatrix4xvAPPLE(0, 1, GL_FALSE, IPLGLMatrixStack_GetMVPx());

	// RUIZD: Change later
	// IPLGLUtil_SetUniformColor4x( _nativeColorR , _nativeColorG, _nativeColorB, _nativeColorA );
	glColor4f (_nativeColorR, _nativeColorG, _nativeColorB, _nativeColorA);

	GLfloat vertices[] =
	{
		IPLMath_IntToFixed(x - SCREEN_WIDTH_D2),  IPLMath_IntToFixed(SCREEN_HEIGHT_D2 - y), 0, //1.0f,
	};

	//GLuint mBufferNames;
	//glGenBuffers(1,&mBufferNames);
	//glBindBuffer(GL_ARRAY_BUFFER, mBufferNames);
	//glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * 4, (const GLvoid*)vertices, GL_STATIC_DRAW);

	//glVertexAttribPointer( 0, 4, GL_FIXED, GL_FALSE, 0, vertices );
	//glEnableVertexAttribArray( 0 );

	//draw the point
	//glDrawArrays( GL_POINTS, 0, 1 );
	//tIPLGeometry  geom;
	_geom.mGeometryMode     = GL_POINTS;
	_geom.mCount            = 1;
	_geom.mpVertexPositions = vertices;
	_geom.mpVertexColors    = NULL;
	_geom.mpTextureCoords   = NULL;
	//	IPLGLUtil_SetUniformColor4xv(color);
	IPLGeometry_DrawDirect(&_geom);

	//glDeleteBuffers( 1, &mBufferNames );
	//glBindBuffer(GL_ARRAY_BUFFER, 0);
}
